package com.gopay.bis.manager.bank.expay;

import java.io.UnsupportedEncodingException;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.dao.bankorder.BankContractInfoDAO;
import com.gopay.bis.manager.bank.payconfig.SmsSupportService;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.spdb.expay.SpdbMessageExPay;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.user.mcc.UserMccTransformReq;
import com.gopay.common.domain.user.mcc.UserMccTransformRes;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.mcc.manager.UserMccTransformManager;
import com.gopay.common.util.DateUtils;
import com.gopay.remote.bank.businesses.ExPayService;

/**
 * 浦发快捷支付报文拼装
 * 
 * @SpdbExPayManager.java
 * @author w_jiqing
 * @2016年6月16日 下午3:51:34 www.gopay.com.cn Inc.All rights reserved.
 */
public class SpdbExPayManager {

    @Resource(name = "spdbConfig")
    private Map<String, String> spdbConfig;
    @Resource(name = "spdbExPayServiceClient")
    private ExPayService spdbExPayServiceClient;
    @Resource(name = "smsSupportService")
    private SmsSupportService smsSupportService;
    @Resource(name = "bankContractInfoDAO")
    private BankContractInfoDAO bankContractInfoDAO;
    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;
    @Resource(name = "userMccTransformManager")
    private UserMccTransformManager userMccTransformManager;

    public static final String IDENTITY_TYPE = "01"; // 身份证
    public static final String IDENTITY_CARD = "IDENTITY_CARD"; // 证件类型
    public static final String CHANNELID_PC = "1"; // pc端
    public static final String CHANNELID_MOBILE = "2"; // 移动端

    /**
     * 快捷签约---0接口
     * 
     * @param msg
     * @return
     * @throws GopayException
     */
    public Object certification(ExPayBaseMessage msg) throws GopayException {
        SpdbMessageExPay message = new SpdbMessageExPay();
        BeanUtils.copyProperties(msg, message);
        CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
        message.setTranAbb((String) spdbConfig.get("SPDB.EXPAY.SIGN.TRANABBR"));
        message.setTranType(spdbConfig.get("SPDB.EXPAY.SIGNVERIFY.TRANTYPE.ZERO"));
        message.setMercId(message.getIdentityCode());
        String mercDtTm = DateUtils.format(mainOrder.getGopayTxnTm());
        message.setMercDtTm(mercDtTm);
        message.setMercCode(message.getMerID());
        message.setIdNo(message.getIdentityCode());
        message.setPayCardName(message.getCardHolder());
        message.setCheckFlag(spdbConfig.get("SPDB.EXPAY.CHECKFLAG"));
        message.setAccount(message.getCardNo());
        message.setBankUrl(message.getPayUrl());
        message.setMobileNo(message.getMediaId());
        if (IDENTITY_TYPE.equals(message.getIdentityType())) {
            message.setIdType((String) spdbConfig.get("SPDB.EXPAY.IDTYPE"));
        } else {
            message.setIdType(message.getIdentityType());
        }
        if ((BisBankBusinessProd._15.value).equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.D"));
        } else if (BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.C"));
            message.setValidThru(changeAvailableDate(message.getAvailableDate()));
        }
        if (CHANNELID_PC.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.MOBILE"));
        } else if (CHANNELID_MOBILE.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.PC"));
        }
        String plainMessage = buildSignMessage(message);
        message.setPlainMessage(plainMessage);
        BankLogUtils.printExPayManagerSignSendLog(message);
        ExPayBaseMessage expayMessage = (ExPayBaseMessage) spdbExPayServiceClient.certification(message);
        BankLogUtils.printExPayManagerSignReturnLog(expayMessage);
        return expayMessage;
    }

    /**
     * 快捷签约----1接口
     * 
     * @param msg
     * @return
     * @throws GopayException
     */
    public Object sendSpdbSMS(ExPayBaseMessage msg) throws GopayException {
        SpdbMessageExPay message = new SpdbMessageExPay();
        BeanUtils.copyProperties(msg, message);
        CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
        message.setTranAbb((String) spdbConfig.get("SPDB.EXPAY.SIGN.TRANABBR"));
        message.setTranType(spdbConfig.get("SPDB.EXPAY.SIGNVERIFY.TRANTYPE.ONE"));
        String verifycode = message.getValidateCode();
        message.setVerifyCode(verifycode);
        message.setMercId(message.getIdentityCode());
        String mercDtTm = DateUtils.format(mainOrder.getGopayTxnTm());
        message.setMercDtTm(mercDtTm);
        message.setMercCode(message.getMerID());
        message.setIdNo(message.getIdentityCode());
        message.setPayCardName(message.getCardHolder());
        message.setCheckFlag(spdbConfig.get("SPDB.EXPAY.CHECKFLAG"));
        message.setAccount(message.getCardNo());
        message.setBankUrl(message.getPayUrl());
        message.setMobileNo(message.getMediaId());
        if (IDENTITY_TYPE.equals(message.getIdentityType())) {
            message.setIdType((String) spdbConfig.get("SPDB.EXPAY.IDTYPE"));
        } else {
            message.setIdType(message.getIdentityType());
        }
        if ((BisBankBusinessProd._15.value).equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.D"));
        } else if (BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.C"));
            message.setValidThru(changeAvailableDate(message.getAvailableDate()));// 有效期
        }
        if (CHANNELID_PC.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.MOBILE"));
        } else if (CHANNELID_MOBILE.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.PC"));
        }
        String plainMessage = buildSignMessage(message);
        message.setPlainMessage(plainMessage);
        BankLogUtils.printExPayManagerSignSendLog(message);
        SpdbMessageExPay expayMessage = (SpdbMessageExPay) spdbExPayServiceClient.certification(message);
        expayMessage.setMediaId(message.getMediaId());
        BankLogUtils.printExPayManagerSignReturnLog(expayMessage);
        return expayMessage;
    }

    /**
     * 快捷签约----2接口
     * 
     * @param msg
     * @return
     * @throws GopayException
     */
    public Object sendSpdbResult(ExPayBaseMessage msg) throws GopayException {
        SpdbMessageExPay message = new SpdbMessageExPay();
        BeanUtils.copyProperties(msg, message);
        CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
        message.setTermCode((String) spdbConfig.get("SPDB.EXPAY.TERMCODE"));
        message.setTranAbb((String) spdbConfig.get("SPDB.EXPAY.SIGN.TRANABBR"));
        message.setTranType(spdbConfig.get("SPDB.EXPAY.SIGNVERIFY.TRANTYPE.ONE"));
        message.setMercId(message.getIdentityCode());
        String mercDtTm = DateUtils.format(mainOrder.getGopayTxnTm());
        message.setMercDtTm(mercDtTm);
        message.setMercCode(message.getMerID());
        message.setIdNo(message.getIdentityCode());
        message.setPayCardName(message.getCardHolder());
        message.setCheckFlag(spdbConfig.get("SPDB.EXPAY.CHECKFLAG"));
        message.setAccount(message.getCardNo());
        message.setBankUrl(message.getPayUrl());
        message.setMobileNo(message.getMediaId());
        if (IDENTITY_TYPE.equals(message.getIdentityType())) {
            message.setIdType((String) spdbConfig.get("SPDB.EXPAY.IDTYPE"));
        } else {
            message.setIdType((String) spdbConfig.get("SPDB.EXPAY.IDTYPE"));
        }
        if ((BisBankBusinessProd._15.value).equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.D"));
        } else if (BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.C"));
            message.setValidThru(changeAvailableDate(message.getAvailableDate()));// 有效期
        }
        if (CHANNELID_PC.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.MOBILE"));
        } else if (CHANNELID_MOBILE.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.PC"));
        }
        String verifycode = message.getValidateCode();
        message.setVerifyCode(verifycode);
        String plainMessage = buildSignMessage(message);
        message.setPlainMessage(plainMessage);
        BankLogUtils.printExPayManagerSignSendLog(message);
        ExPayBaseMessage expayMessage = (ExPayBaseMessage) spdbExPayServiceClient.certification(message);
        BankLogUtils.printExPayManagerSignReturnLog(expayMessage);
        return expayMessage;
    }

    /**
     * 快捷支付----付款接口
     * 
     * @param msg
     * @return
     * @throws GopayException
     */
    public Object payment(ExPayBaseMessage msg) throws GopayException {
        SpdbMessageExPay message = (SpdbMessageExPay) msg;
        CpsGenMainOrder mainOrder = mainOrderQuery.get(message.getOrderId());
        message.setTermCode((String) spdbConfig.get("SPDB.EXPAY.TERMCODE"));
        message.setTranAbb((String) spdbConfig.get("SPDB.EXPAY.PAYMENT.TRANABBR")); // 交易缩写（对私KPER）
                                                                                    // //
                                                                                    // KPER
                                                                                    // //
                                                                               // 快捷支付（对私）
        message.setMercId(message.getIdentityCode());
        String mercDtTm = DateUtils.format(mainOrder.getGopayTxnTm());
        message.setMercDtTm(mercDtTm);
        message.setTermSsn(message.getBankOrderId());
        message.setMercCode(message.getMerID());
        message.setIdNo(message.getIdentityCode());
        message.setAccount(message.getCardNo());
        message.setPayCardName(message.getCardHolder());
        message.setMobileNo(message.getMediaId());
        message.setTranAmt(message.getAmount().toString());
        message.setTransPrincipal(message.getAmount().toString());
        message.setCurrency((String) spdbConfig.get("SPDB.EXPAY.CURRENCY"));
        System.out.println("~~~~~~~~" + spdbConfig.get("SPDB.EXPAY.CURRENCY"));
        System.out.println("~~~~~~~~" + message.getCurrency());
        if (IDENTITY_CARD.equals(message.getIdentityType())) {
            message.setIdType((String) spdbConfig.get("SPDB.EXPAY.IDTYPE"));
        } else {
            message.setIdType(message.getIdentityType());
        }
        if ((BisBankBusinessProd._15.value).equals(message.getBankBusProd().value)) {
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.D"));
        } else if (BisBankBusinessProd._05.value.equals(message.getBankBusProd().value)) {
            message.setIsInstl((String) spdbConfig.get("SPDB.EXPAY.ISINSTL"));
            message.setAccountType((String) spdbConfig.get("SPDB.EXPAY.ACCOUNTTYPE.C"));
            message.setValidThru(message.getAvailableDate());// 有效期
        }
        if (CHANNELID_PC.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.MOBILE"));
        } else if (CHANNELID_MOBILE.equals(message.getTermination())) {
            message.setMerChannelId((String) spdbConfig.get("SPDB.EXPAY.MERCHANNELID.PC"));
        }
        // 二级商户号报备
        UserMccTransformReq userM = new UserMccTransformReq();
        userM.setBankCode(BankConstants.BANK_LOGO_SPDB);
        userM.setCustId(msg.getSpecial2());
        UserMccTransformRes userRes = userMccTransformManager.graspUserMccInfo(userM);
        if (userRes == null) {
            if ((BankConstants.GOPAY_CHONGZHI_CUSTID).equals(msg.getSpecial2())) {
                message.setSubMercFlag((String) spdbConfig.get("SPDB.EXPAY.SUBMERCFLAG.XUNI"));
                message.setSubMercName(BankConstants.GOPAY_NAME);
                message.setSubMercGoodsName("国付宝充值");
            }
        } else {
            // p2p商户上送mcc处理
            if (BankConstants.GOPAY_MCC_CODE.equals(userRes.getGopayMccCode())) {
                message.setSubMercFlag((String) spdbConfig.get("SPDB.EXPAY.SUBMERCFLAG.SHIWU"));
                message.setSubMercName("（");
                message.setSubMercGoodsName("平台服务）");
            } else {
                // 非p2p商户信息报备
                message.setSubMercFlag((String) spdbConfig.get("SPDB.EXPAY.SUBMERCFLAG.SHIWU"));
                message.setSubMercName(userRes.getCorpName());
                message.setSubMercGoodsName(userRes.getBankMccDesc());
                if (BankConstants.BANK_MCC_CODE_7375.equals(userRes.getBankMccCode())
                        || BankConstants.BANK_MCC_CODE_4814.equals(userRes.getBankMccCode())
                        || BankConstants.BANK_MCC_CODE_4816.equals(userRes.getBankMccCode())) {
                    // 信息检索服务、计算机网络、电信服务归属于消费虚拟类
                    message.setSubMercFlag((String) spdbConfig.get("SPDB.EXPAY.SUBMERCFLAG.XUNI"));
                }
            }
        }
        String plainMessage = buildPayMessage(message);
        message.setPlainMessage(plainMessage);
        BankLogUtils.printExPayManagerSignSendLog(message);
        ExPayBaseMessage expayMessage = (ExPayBaseMessage) spdbExPayServiceClient.payment(message);
        BankLogUtils.printExPayManagerSignReturnLog(expayMessage);
        return expayMessage;
    }

    /**
     * 快捷单笔订单查询
     * 
     * @param baseMsg
     * @return
     * @throws GopayException
     */
    public Object query(ExPayBaseMessage baseMsg) throws GopayException {
        SpdbMessageExPay message = new SpdbMessageExPay();
        BeanUtils.copyProperties(baseMsg, message);
        message.setTermCode((String) spdbConfig.get("SPDB.EXPAY.TERMCODE"));
        message.setMercCode(message.getMerID());
        message.setTransName((String) spdbConfig.get("SPDB.EXPAY.QUERY.TRANABBR"));
        message.setTranAbb((String) spdbConfig.get("SPDB.EXPAY.QUERY.TRANABBR"));
        message.setoTranAbbr((String) spdbConfig.get("SPDB.EXPAY.PAYMENT.TRANABBR"));
        message.setTermSsn(message.getBankOrderId());
        message.setPlainMessage(buildQuery(message));
        BankLogUtils.printExPayManagerQuerySendLog(message);
        message = (SpdbMessageExPay) spdbExPayServiceClient.queryOrder(message);
        BankLogUtils.printExPayManagerQueryReturnLog(message);
        return message;
    }

    /**
     * 构建签约报文
     * 
     * @param message
     * @return
     * @throws GopayException
     */
    private String buildSignMessage(SpdbMessageExPay message) throws GopayException {
        StringBuffer sb = new StringBuffer();
        try {
            sb.append("TranAbbr=").append(message.getTranAbb()).append("|");
            sb.append("TranType=").append(message.getTranType()).append("|");
            if (spdbConfig.get("SPDB.EXPAY.SIGNVERIFY.TRANTYPE.ONE").equals(message.getTranType())) {
                sb.append("VerifyCode=").append(message.getVerifyCode()).append("|");
            }
            sb.append("Merc_id=").append(message.getMercId()).append("|");
            sb.append("MercDtTm=").append(message.getMercDtTm()).append("|");
            sb.append("CheckFlag=").append(message.getCheckFlag()).append("|");
            sb.append("IdType=").append(message.getIdType()).append("|");
            sb.append("IdNo=").append(message.getIdNo()).append("|");
            sb.append("AccountType=").append(message.getAccountType()).append("|");
            sb.append("Account=").append(message.getAccount()).append("|");
            sb.append("PayCardName=").append(java.net.URLEncoder.encode(message.getPayCardName(), "GBK")).append("|");
            sb.append("MobileNo=").append(message.getMobileNo()).append("|");
            if ("1".equals(message.getAccountType())) {
                sb.append("CVV2=").append("|");
            } else {
                sb.append("CVV2=").append(message.getCvv2()).append("|");
            }
            sb.append("ValidThru=").append(message.getValidThru()).append("|");
            sb.append("MercCode=").append(message.getMercCode()).append("|");
            sb.append("MercUrl=").append(message.getMercUrl()).append("|");
            sb.append("MerChannelId=").append(message.getMerChannelId());
        } catch (UnsupportedEncodingException e) {
            BankLogUtils.printManagerExceptionLog(e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6053);
        }
        return sb.toString();
    }

    /**
     * 构建支付报文
     * 
     * @param message
     * @return
     */
    private String buildPayMessage(SpdbMessageExPay message) throws GopayException {
        StringBuffer sb = new StringBuffer();
        try {
            sb.append("TranAbbr=").append(message.getTranAbb()).append("|");
            sb.append("Merc_id=").append(message.getMercId()).append("|");
            sb.append("MercDtTm=").append(message.getMercDtTm()).append("|");
            sb.append("TermSsn=").append(message.getTermSsn()).append("|");
            sb.append("MercCode=").append(message.getMercCode()).append("|");
            if (StringUtils.isBlank(message.getSubMercName())) {
                sb.append("SubMercName=").append(message.getSubMercName()).append("|");
            } else {
                sb.append("SubMercName=").append(java.net.URLEncoder.encode(message.getSubMercName(), "GBK"))
                        .append("|");
            }
            sb.append("IdType=").append(message.getIdType()).append("|");
            sb.append("IdNo=").append(message.getIdNo()).append("|");
            sb.append("AccountType=").append(message.getAccountType()).append("|");
            sb.append("Account=").append(message.getAccount()).append("|");
            sb.append("PayCardName=").append(java.net.URLEncoder.encode(message.getPayCardName(), "GBK")).append("|");
            sb.append("MobileNo=").append(message.getMediaId()).append("|");
            sb.append("ValidThru=").append(message.getValidThru()).append("|");
            sb.append("IsInstl=").append(message.getIsInstl()).append("|");
            sb.append("TermCode=").append(message.getTermCode()).append("|");
            sb.append("TranAmt=").append(message.getTranAmt()).append("|");
            sb.append("Remark1=").append(message.getRemark1()).append("|");
            sb.append("Remark2=").append(message.getRemark2()).append("|");
            sb.append("MercUrl=").append(message.getMercUrl()).append("|");
            sb.append("TransPrincipal=").append(message.getTransPrincipal()).append("|");
            sb.append("SubMercFlag=").append(message.getSubMercFlag()).append("|");
            if (StringUtils.isBlank(message.getSubMercGoodsName())) {
                sb.append("SubMercGoodsName=").append(message.getSubMercGoodsName()).append("|");
            } else {
                sb.append("SubMercGoodsName=").append(java.net.URLEncoder.encode(message.getSubMercGoodsName(), "GBK"))
                        .append("|");
            }
            sb.append("Currency=").append(message.getCurrency()).append("|");
            sb.append("MerChannelId=").append(message.getMerChannelId());
        } catch (UnsupportedEncodingException e) {
            BankLogUtils.printManagerExceptionLog(e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6053);
        }

        return sb.toString();
    }

    /**
     * 构建支付查询报文
     * 
     * @param message
     * @return
     */
    private String buildQuery(SpdbMessageExPay message) {
        StringBuffer sb = new StringBuffer();
        sb.append("MercCode=").append(message.getMercCode()).append("|");
        sb.append("OTranAbbr=").append(message.getoTranAbbr()).append("|");
        sb.append("TermSsn=").append(message.getBankOrderId());
        return sb.toString();
    } 

    /**
     * 转换信用卡有效期格式 默认 MMYY 有些银行为YYMM
     * 
     * @param str
     * @return
     */
    private String changeAvailableDate(String str) {
        return str.substring(2) + str.substring(0, 2);
    }

}
